1、 PWM 子系统
	Linux 内核提供了个 PWM 子系统框架，其核心是 struct pwm_chip 结构体，其核心成员如下：
	//指向提供PWM的设备
	struct device *dev;
	//PWM控制器底层操作函数
	const struct pwm_ops *ops;
	//PWM通道数量
	unsigned int npwm;
	//pwm请求函数，一般为赋值为of_pwm_xlate_with_flags
	struct pwm_device * (*of_xlate)(struct pwm_chip *pc, const struct of_phandle_args *args);
	//使用PWM节点时需要几个参数，一般是2或者3，例如：为3时需要指定编号、周期、标志三种信息，为2时没有标志信息
	unsigned int of_pwm_n_cells;
	结构体 struct pwm_ops 提供操作PWM控制的底层函数，其主要成员有：
	//请求PWM，可选
	int (*request)(struct pwm_chip *chip, struct pwm_device *pwm);
	//释放PWM，可选
	void (*free)(struct pwm_chip *chip, struct pwm_device *pwm);
	//捕获PWM信号
	int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm, 
					struct pwm_capture *result, unsigned long timeout);
	//设置PWM信号，包括基本配置、使能、禁止等操做
	int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
				const struct pwm_state *state);
	//获取PWM状态，只在注册时被调用一次，可选
	void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
					struct pwm_state *state);
	//指向当前所属内核模块
	struct module *owner;
	向内核注册PWM控制器
	int pwmchip_add(struct pwm_chip *chip)
	从内核中删除PWM控制器
	int pwmchip_remove(struct pwm_chip *chip)
2、使用 STM32 PWM 驱动
	STM32 的 PWM 是采用定时器产生的，并在内核中已经提供了相应的驱动，只需要修改相应的设备树即可，因为 PWM 是
采用定时器，所以这里需要同时关注定时器设备树节点和 PWM 设备树节点。
	定时器设备树节点参考文档Documentation/devicetree/bindings/mfd/stm32-timers.txt，其中参数有：
	compatible 属性，必须为 "st,stm32-pwm"
	reg 属性，定时器物理寄存器基地址
	clock-names 属性，应设置为 "int"
	clocks 属性，指定定时器时钟源
	dmas 属性，指定定时器的DMA触发源
	dma-names 属性，与dmas属性对应，指定相应触发源的名称
	pwm 子节点，描述 PWM 相关信息，对应的参考文档为Documentation/devicetree/bindings/pwm/pwm-stm32.txt
	timer 子节点，描述定时相关信息，对应的参考文档为Documentation/devicetree/bindings/iio/timer/stm32-timer-t
rigger.txt
	counter 子节点，描述计数相关信息，对应的参考文档为Documentation/devicetree/bindings/counter/stm32-timer-c
nt.txt
	如下是一个定时器节点的基本结构：
	timers1: timer@44000000 {
		#address-cells = <1>;
		#size-cells = <0>;
		compatible = "st,stm32-timers";
		reg = <0x44000000 0x400>;
		clocks = <&rcc TIM1_K>;
		clock-names = "int";
		dmas = <&dmamux1 11 0x400 0x80000001>,
		       <&dmamux1 12 0x400 0x80000001>,
		       <&dmamux1 13 0x400 0x80000001>,
		       <&dmamux1 14 0x400 0x80000001>,
		       <&dmamux1 15 0x400 0x80000001>,
		       <&dmamux1 16 0x400 0x80000001>,
		       <&dmamux1 17 0x400 0x80000001>;
		dma-names = "ch1", "ch2", "ch3", "ch4",
			    "up", "trig", "com";
		status = "disabled";

		pwm {
			compatible = "st,stm32-pwm";
			#pwm-cells = <3>;
			status = "disabled";
		};

		timer@0 {
			compatible = "st,stm32h7-timer-trigger";
			reg = <0>;
			status = "disabled";
		};

		counter {
			compatible = "st,stm32-timer-counter";
			status = "disabled";
		};
	};
	PWM 子节点设备树节点参考文档Documentation/devicetree/bindings/pwm/pwm-stm32.txt，其中参数有：
	compatible 属性，必须为 "st,stm32-pwm"
	pinctrl-n 属性，指定 WPM 的引脚，至少包含一组 default 引脚，也可以添加一组 sleep 引脚
	pinctrl-names 属性，与 pinctrl-n 属性配合使用，指定引脚组的名称，必须要包含一组 default ，也可以添加一组
sleep
	#pwm-cells 属性，引用 PWM 时指定的参数个数，应该设置为 3
	st,breakinput 属性，配置断路输入，有3个参数，分别是断路输入编号（即使用那路信号）、有效电平（0低电平，1高电平）、
滤波值
	如下是一个PWM节点的基本结构
		timers@40010000 {
		......
		pwm {
			compatible = "st,stm32-pwm";
			#pwm-cells = <3>;
			pinctrl-0 = <&pwm1_pins>;
			pinctrl-1 = <&pwm1_sleep_pins>;
			pinctrl-names = "default", "sleep";
			st,breakinput = <0 1 5>;
		};
		......
	};
	内核中使用 PWM ：
	在需要使用 PWM 的节点中定义一个 pwms 属性和一个可选的 pwm-names 属性来描述要使用的 PWM 信号，示例如下：
	bl: backlight {
		//描述所引用的PWM，它有3个参数，分别是通道号、周期、极性
		pwms = <&pwm 0 5000000 PWM_POLARITY_INVERTED>;
		//与pwms对应，指定相应PWM的名称
		pwm-names = "backlight";
	};
	使用函数pwm_device *pwm_get(struct device *dev, const char *consumer)可以从设备中获取 pwm 设备，然后调用
PWM 的控制函数
	使能 STM32 PWM ：
	1）使能 PWM 驱动
	make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- menuconfig
	Device Drivers  --->
		[*] Pulse-Width Modulation (PWM) Support  --->
			<*>   STMicroelectronics STM32 PWM
	2）在 stm32mp15-pinctrl.dtsi 中修改 pwm1 的引脚配置为如下内容（也可在顶层中引用 pinctrl 节点后进行修改）
	pwm1_pins_a: pwm1-0 {
		pins {
			//TIM1_CH3，需要屏蔽PA10在其他地方的使用
			pinmux = <STM32_PINMUX('A', 10, AF1)>;,
			bias-pull-down;
			drive-push-pull;
			slew-rate = <0>;
		};
	};
	pwm1_sleep_pins_a: pwm1-sleep-0 {
		pins {
			//TIM1_CH3，需要屏蔽PA10在其他地方的使用
			pinmux = <STM32_PINMUX('A', 10, ANALOG)>;
		};
	};
	3）在顶层设备树中引用 timers1 节点，并加入如下内容
	&timers1 {
		//使能定时器
		status = "okay";
		//删除DMA相关的属性
		/delete-property/dmas;
		/delete-property/dma-names;
		
		//为内部PWM节点加标签，方便引用
		pwm1: pwm {
			//指定默认引脚
			pinctrl-0 = <&pwm1_pins_a>;
			//指定睡眠状态的引脚
			pinctrl-1 = <&pwm1_sleep_pins_a>;
			//指定上面引脚组的名称
			pinctrl-names = "default", "sleep";
			//使能PWM
			status = "okay";
		};
	};
	4）用make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- dtbs -j8编译设备树，然后使用新的设备树启动，此
时便可使用 timer1 的 pwm3 了
